package com.ys.web.user.login;

import cn.hutool.http.HttpRequest;
import cn.hutool.http.HttpResponse;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.ys.base.BaseConstants;
import com.ys.base.EnumType;
import com.ys.utils.apple.AppleUtils;
import com.ys.utils.base.http.McodeHandler;
import com.ys.utils.base.http.ResponseHandler;
import com.ys.utils.base.j2se.HttpUtil;
import com.ys.utils.base.j2se.Logger;
import com.ys.utils.base.j2se.StringHandler;
import com.ys.utils.base.secret.MD5;
import com.ys.utils.help.UserUtils;
import com.ys.utils.redis.Redis;
import com.ys.utils.redis.key.UserKey;
import com.ys.utils.spring.config.SystemError;
import com.ys.utils.spring.properties.Config;
import com.ys.web.user.app.AppInfo;
import com.ys.web.user.app.AppInfoManager;
import com.ys.web.user.friends.mapper.GroupInfoMapper;
import com.ys.web.user.friends.mapper.UserGroupMapper;
import lombok.extern.slf4j.Slf4j;
import me.chanjar.weixin.common.bean.WxOAuth2UserInfo;
import me.chanjar.weixin.common.bean.oauth2.WxOAuth2AccessToken;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.UUID;

/**
 * Description
 * Created by 王伟
 * Date create on 15:12 2019/11/18.
 */
@Slf4j
@RestController
@RequestMapping("/user/login/")
public class LoginController {
    @Autowired
    private LoginService loginService;

    @Autowired
    private GroupInfoMapper groupInfoMapper;

    @Autowired
    private UserGroupMapper userGroupMapper;


    @Value("${ys.default.head_img}")
    private String DEFAULT_IMG;

//    public byte[] readKey() throws Exception {
//        String temp = "MIGTAgEAMBMGByqGSM49AgEGCCqGSM49AwEHBHkwdwIBAQQg40I8d3djzs6QvOi+BUh7mImb74md40lvC8I49pMs+QqgCgYIKoZIzj0DAQehRANCAAQ6xGkePR25HE+NBYKT1v8rhiP1+JcxRLx9dxyVG9tKtKtvI6/+I/xlVvcd3mSV3lfM1kzfJD4KwjssUxFKHoX1";
//        return Base64.decodeBase64(temp);
//    }

    @PostMapping("validateUser")
    public String validateUser(@RequestAttribute String uid) {
        LoginInfo loginInfo = loginService.infoByUid(uid);
        LoginResult loginResult = UserUtils.getLoginResult();
        if (loginInfo != null) {
            if (loginInfo.getAccountStatus() == 2) {
                loginResult.setMsg("该账号已被禁用");
                String tokenKey = loginService.uToken.get(uid);
                Redis.key.del(tokenKey);
                return ResponseHandler.success(loginResult);
            }
        }
        loginResult.setFlag(true);
        loginService.uToken.remove(uid);
        return ResponseHandler.success(loginResult);
    }


    @PostMapping("getRegisterConfig")
    public String getRegisterConfig() {
        return ResponseHandler.success(Boolean.parseBoolean(Config.pp.getOrDefault(BaseConstants.SwitchConstants.SWITCH_REGISTER, "true")));
    }

    @PostMapping("apple")
    public Object apple(@RequestAttribute String ip,String code, String inviteCode) {
//        try {
//            String client_id = "com.treeshuzhuang.cn";//被授权的APP ID
//            Map<String, Object> header = new HashMap<String, Object>();
//            header.put("kid", "RFRBZZNLQL");
//            Map<String, Object> claims = new HashMap<String, Object>();
//            claims.put("iss", "GQW4SP48W8"); //team id
//            long now = System.currentTimeMillis() / 1000;
//            claims.put("iat", now);
//            claims.put("exp", now + 86400 * 30); // 最长半年，单位秒
//            claims.put("aud", "https://appleid.apple.com"); // 默认值
//            claims.put("sub", client_id);
//            PKCS8EncodedKeySpec pkcs8EncodedKeySpec = new PKCS8EncodedKeySpec(readKey());
//            KeyFactory keyFactory = KeyFactory.getInstance("EC");
//            PrivateKey privateKey = keyFactory.generatePrivate(pkcs8EncodedKeySpec);
//            String client_secret = Jwts.builder().setHeader(header).setClaims(claims).signWith(SignatureAlgorithm.ES256, privateKey).compact();
//            System.out.println(client_secret);
//            String strUri = String.format("https://appleid.apple.com/auth/token?client_id=%s&code=%s&grant_type=%s&client_secret=%s", "com.treeshuzhuang.cn", code, "authorization_code",client_secret);
//            HttpResponse response = HttpRequest.post(strUri).execute();
//            System.out.println(response);
//            if(response.getStatus() == 200){
//                JSONObject jsonObject = JSONObject.parseObject(response.body());
//                String id_token = jsonObject.getString("id_token");
//                if (!AppleUtils.verify(id_token)) {
//                    return ResponseHandler.error("500", "登录失败");
//                }
//                JSONObject json = AppleUtils.parserIdentityToken(id_token);
//                System.out.println(json);
//                LoginInfo loginInfo = new LoginInfo();
//                loginInfo.setAppleId(json.getString("sub"));
//                return ResponseHandler.success(login(loginInfo));
//            }
//        } catch (Exception e) {
//            e.printStackTrace();
//        }
//        return ResponseHandler.error("500", "登录失败");

        try {
            //验证identityToken
            if (!AppleUtils.verify(code)) {
                return ResponseHandler.error("500", "登录失败");
            }
        } catch (Exception e) {
            Boolean verify = false;
            for (int i = 0; i < 3; i++) {
                try {
                    verify = AppleUtils.verify(code);
                    if (verify) {
                        break;
                    }
                } catch (Exception exception) {
                    exception.printStackTrace();
                }
            }
            if (!verify) {
                return ResponseHandler.error("500", "登录失败");
            }
        }
        //对identityToken解码
        JSONObject json = AppleUtils.parserIdentityToken(code);
//        验证通过，入库，生成token登录
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setAppleId(json.getString("sub"));
        return ResponseHandler.success(login(loginInfo, inviteCode,1,ip));
    }

    /**
     * @author 但何非
     * @dateTime 2023/1/8 20:02
     * @params
     * @param ip: 用户ip
     * @param phone: 电话号码
     * @param code: 登录密码
     * @param inviteCode: 推荐码
     * @return java.lang.String
     * @Description:账号密码登录
     */
    @RequestMapping("phone/login")
    public String phoneLogin(@RequestAttribute String ip, String phone, String code, String inviteCode) {
        if (StringHandler.isEmpty(phone) || StringHandler.isEmpty(code)) {
            SystemError.wrapBs("500", "账号或密码错误");
        }
        if (phone.equals(StringHandler.getString(Config.pp.get("about.us.phone.id"),BaseConstants.ClientConstants.CLIENT_PHONE))) {
            if (!code.equals(StringHandler.getString(Config.pp.get("about.us.phone.password"),"ys111222"))) {
                Logger.error("用户信息：" + phone);
                SystemError.wrapBs("500", "账号或密码错误.");
            }
            Map<String, Object> loginUser = new HashMap<>();
            loginUser.put("alias", McodeHandler.to32Radix(BaseConstants.ClientConstants.CLIENT_ID));//用户别名，用于绑定消息推送
            loginUser.put("nickName", BaseConstants.ClientConstants.CLIENT_NICK_NAME);
            loginUser.put("avatarUrl", BaseConstants.ClientConstants.CLIENT_HEAD_IMG);
            loginUser.put("havePhone", true);
            String token = MD5.md5(StringHandler.getString(BaseConstants.ClientConstants.CLIENT_PHONE + System.currentTimeMillis()));
            String tokenKey = UserKey.uidByToken(token);
            Redis.str.set(tokenKey, StringHandler.getString(BaseConstants.ClientConstants.CLIENT_ID), 60 * 60 * 24);
            loginUser.put("token", token);
            return ResponseHandler.success(loginUser);
        }
        LoginInfo loginInfo = loginService.infoByPhone(phone);
        if (StringHandler.isEmpty(loginInfo) || StringHandler.isEmpty(loginInfo.getPassword()) || !loginInfo.getPassword().equals(MD5.md5(code + loginInfo.getSalt()))) {
            Logger.error("用户信息：" + JSON.toJSONString(loginInfo));
            SystemError.wrapBs("500", "账号或密码错误.");
        }
        if(Config.pp.get("phone.black").contains(phone)){
            SystemError.wrapBs(EnumType.ResponseCode.ILLEGAL.getCode(), "系统繁忙");
        }
        //验证通过
        return ResponseHandler.success(login(loginInfo, inviteCode,1,ip));
    }

    /**
     * 忘记密码
     *
     * @param code
     * @return
     */
    @RequestMapping("phone/forgetPass")
    public String phoneForgetPass(String phone, String sms, String code) {
        if (StringHandler.isEmpty(phone)) {
            SystemError.wrapBs("500", "账号或密码错误");
        }
        LoginInfo loginInfo = loginService.infoByPhone(phone);
        if(StringHandler.isEmpty(loginInfo)){
            SystemError.wrapBs("500", "手机号错误，如果是新用户请直接验证码登录即可");
        }
        if (!StringHandler.isPattern(code, "[a-z]+|[A-Z]+") || !StringHandler.isPattern(code, "\\d+") || code.matches("\\W") || code.length() < 8 || code.length() > 20) {
            SystemError.wrapBs("500", "密码为8到20位且包含字母与数字的组合");
        }
        String sms2 = Redis.str.get(UserKey.codeByPhone(phone));
        if (StringHandler.isEmpty(sms2)) {
            SystemError.wrapBs("500", "请先获取验证码");
        }
        if (!sms2.equals(sms)) {
            SystemError.wrapBs("500", "验证码已过期");
        }
        if(StringHandler.isEmpty(loginInfo.payPass)){
            loginInfo.setSalt(UUID.randomUUID().toString().substring(0, 4));
        }
        loginInfo.setPassword(MD5.md5(code + loginInfo.getSalt()));
        int i = loginService.updatePassWord(loginInfo);
        if (i != 1) {
            SystemError.wrapBs("500", "网络异常");
        }
        //验证通过
        return ResponseHandler.success();
    }

    /**
     * 密码设置
     *
     * @param code
     * @return
     */
    @RequestMapping("phone/setPass")
    public String phoneSetPass(@RequestAttribute String uid, String code) {
        if (!StringHandler.isPattern(code, "[a-z]+|[A-Z]+") || !StringHandler.isPattern(code, "\\d+") || code.matches("\\W") || code.length() < 8 || code.length() > 20) {
            SystemError.wrapBs("500", "密码为8到20位且包含字母与数字的组合");
        }
        LoginInfo loginInfo = loginService.infoByUid(uid);
        if(StringHandler.isEmpty(loginInfo.payPass)){
            loginInfo.setSalt(UUID.randomUUID().toString().substring(0, 4));
        }
        loginInfo.setPassword(MD5.md5(code + loginInfo.getSalt()));
        int i = loginService.updatePassWord(loginInfo);
        if (i != 1) {
            SystemError.wrapBs("500", "网络异常");
        }
        //验证通过
        return ResponseHandler.success();
    }

    /**
     * 密码修改
     *
     * @param oldCode
     * @param code
     * @return
     */
    @RequestMapping("phone/upPass")
    public String phoneUpPass(String phone, String sms, String oldCode, String code) {
        if (!StringHandler.isPattern(code, "[a-z]+|[A-Z]+") || !StringHandler.isPattern(code, "\\d+") || code.matches("\\W") || code.length() < 8 || code.length() > 20) {
            SystemError.wrapBs("500", "密码为8到20位且包含字母与数字的组合");
        }
        String sms2 = Redis.str.get(UserKey.codeByPhone(phone));
        if (StringHandler.isEmpty(sms2)) {
            SystemError.wrapBs("500", "请先获取验证码");
        }
        if (!sms2.equals(sms)) {
            SystemError.wrapBs("500", "验证码已过期");
        }
        LoginInfo loginInfo = loginService.infoByPhone(phone);
        if(StringHandler.isEmpty(loginInfo.payPass)){
            loginInfo.setSalt(UUID.randomUUID().toString().substring(0, 4));
        }
        String pass = MD5.md5(oldCode + loginInfo.getSalt());
        if (StringHandler.isEmpty(loginInfo) || StringHandler.isEmpty(loginInfo.getPassword()) || !loginInfo.getPassword().equals(pass)) {
            SystemError.wrapBs("500", "原密码输入错误");
        }

        loginInfo.setPassword(MD5.md5(code + loginInfo.getSalt()));
        int i = loginService.updatePassWord(loginInfo);
        if (i != 1) {
            SystemError.wrapBs("500", "网络异常");
        }
        //验证通过
        return ResponseHandler.success();
    }

    /**
     * @author 但何非
     * @dateTime 2023/1/8 20:01
     * @params
     * @param ip: 用户ip
     * @param phone: 电话号码
     * @param code: 验证码
     * @param inviteCode:推荐码
     * @return java.lang.String
     * @Description:手机号登录,登录就注册为普通用户
     */
    @RequestMapping("phone")
    public String phone(@RequestAttribute String ip, String phone, String code, String inviteCode) {
        if(Config.pp.get("phone.black").contains(phone)){
            SystemError.wrapBs(EnumType.ResponseCode.ILLEGAL.getCode(), "系统繁忙");
        }
        String sms = Redis.str.get(UserKey.codeByPhone(phone));
        if (StringHandler.isEmpty(sms)) {
            SystemError.wrapBs("500", "请先获取验证码");
        }
        if (!sms.equals(code)) {
            SystemError.wrapBs("500", "验证码已过期");
        }
        //验证通过，入库，生成token登录
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setPhone(phone);
        return ResponseHandler.success(login(loginInfo, inviteCode,1,ip));
    }

    @RequestMapping("phone/reg")
    public String phoneReg(@RequestAttribute String ip, String phone, String code, String inviteCode,String passWord,String passWordCk) {
        if(StringHandler.isEmpty(passWord)){
            SystemError.wrapBs("500", "密码不能为空");
        }
        if(StringHandler.isEmpty(passWordCk)){
            SystemError.wrapBs("500", "确认密码不能为空");
        }
        if(!passWord.equals(passWordCk)){
            SystemError.wrapBs("500", "两次密码输入不一致");
        }
        if(Config.pp.get("phone.black").contains(phone)){
            SystemError.wrapBs(EnumType.ResponseCode.ILLEGAL.getCode(), "系统繁忙");
        }
        String sms = Redis.str.get(UserKey.codeByPhone(phone));
        if (StringHandler.isEmpty(sms)) {
            SystemError.wrapBs("500", "请先获取验证码");
        }
        if (!sms.equals(code)) {
            SystemError.wrapBs("500", "验证码已过期");
        }
        //验证通过，入库，生成token登录
        LoginInfo loginInfo = new LoginInfo();
        loginInfo.setPhone(phone);
        loginInfo.setSalt(UUID.randomUUID().toString().substring(0, 4));
        loginInfo.setPassword(MD5.md5(passWord + loginInfo.getSalt()));
        return ResponseHandler.success(login(loginInfo, inviteCode,3,ip));
    }

    /**
     * @author 但何非
     * @dateTime 2023/1/8 20:01
     * @params
     * @param ip: 用户ip
     * @param code: 微信授权返回code
     * @return java.lang.String
     * @Description:微信登录,登录就注册为普通用户
     */
    @RequestMapping("wx")
    public String wx(@RequestAttribute String ip, String code) {
        if (StringHandler.isEmpty(code)) {
            SystemError.wrapBs("500", "登录失败");
        }
        //参数判断
        //app判断
        AppInfo appInfo = AppInfoManager.get(Config.pp.get("appId"));
        if (null == appInfo) {
            return ResponseHandler.error("8002", "参数异常");
        }
        LoginInfo loginInfo = null;
        try {
            String strUri = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appInfo.getAppId(), appInfo.getSecret(), code);
            // 使用 Hutool开发工具包，执行请求接口，获取相关信息
            HttpResponse response = HttpRequest.get(strUri).execute();
            WxOAuth2AccessToken token = WxOAuth2AccessToken.fromJson(response.body());
            // 判断JSON对象中 unionid 是否存在
            if (StringHandler.isEmpty(token.getUnionId())) {
                // 不存在返回结果，code无效
                SystemError.wrapBs("500", "登录失败");
            }
            if(Config.pp.get("wx.black").contains(token.getUnionId())){
                SystemError.wrapBs(EnumType.ResponseCode.ILLEGAL.getCode(), "系统繁忙、");
            }
            strUri = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s", token.getAccessToken(), token.getOpenId(), "zh_CN");
            response = HttpRequest.get(strUri).execute();
            WxOAuth2UserInfo wxOAuth2UserInfo = WxOAuth2UserInfo.fromJson(response.body());

            loginInfo = WxOAuth2UserInfoTransformer.INSTANCE.apply(wxOAuth2UserInfo);
            loginInfo.setAppId(appInfo.getAppId());
        } catch (Exception e) {
            Logger.error("微信登录", e);
            return ResponseHandler.error("8003", "微信信息异常，解析失败");
        }
        return ResponseHandler.success(login(loginInfo, "0",4,ip));
    }

    /**
     * @author 但何非
     * @dateTime 2023/1/8 19:59
     * @params
     * @param wxLoginInfo:用户信息
     * @param inviteCode:推荐码
     * @param type: 1 登录 2 获取用户信息 3 手机注册 4 微信注册
     * @param ip:用户ip
     * @return java.util.Map<java.lang.String,java.lang.Object>
     * @Description:登录的公共逻辑
     */
    private Map<String, Object> login(LoginInfo wxLoginInfo, String inviteCode,int type,String ip) {
        HttpUtil.userIpAdds(ip);
        //查询用户信息排除封号的用户
        LoginInfo loginInfo = null;
        if (StringHandler.isNotEmpty(wxLoginInfo.getPhone())) {
            loginInfo = loginService.infoByPhone(wxLoginInfo.getPhone());
        } else if (StringHandler.isNotEmpty(wxLoginInfo.getUnionId())) {
            loginInfo = loginService.info(wxLoginInfo.getUnionId());
        } else if (StringHandler.isNotEmpty(wxLoginInfo.getAppleId())) {
            loginInfo = loginService.infoByApple(wxLoginInfo.getAppleId());
        }
        if (StringHandler.isNotEmpty(loginInfo) && loginInfo.getAccountStatus()!=1) {
            loginInfo.ip = ip;
            if(type==1){
                loginService.updateUserIp(loginInfo);
            }
            return loginService.loginUser(loginInfo);
        } else {
            if(type!=3 && type!=4){
                SystemError.wrapBs("500", "该用户不存在，请注册后登录");
            }
            boolean flag = Boolean.parseBoolean(Config.pp.getOrDefault(BaseConstants.SwitchConstants.SWITCH_REGISTER, "false"));
            if (!flag) {
                SystemError.wrapBs("500", "系统优化中，暂无法注册！");
            }
            long inviteUid =0L;
            boolean isInvited = Boolean.parseBoolean(Config.pp.getOrDefault(BaseConstants.SwitchConstants.SWITCH_INVITE_CODE, "false"));
            if (isInvited && !"0" .equals(inviteCode)) {
                if (StringHandler.isEmpty(inviteCode)) {
                    SystemError.wrapBs("-1", "邀请码必填");
                }

//            long groupId = 0;
//            try {
//                groupId = McodeHandler.from32Radix(inviteCode.toUpperCase());
//            } catch (Exception e) {
//                SystemError.wrapBs("-1", "邀请码有误");
//            }
//            BaseGroupInfoPO baseGroupInfoPO = groupInfoMapper.selectByPrimaryKey(groupId);
//            if (StringHandler.isEmpty(baseGroupInfoPO)) {
//                SystemError.wrapBs("-1", "邀请码有误");
//            } else {
//                if (!McodeHandler.to32Radix(baseGroupInfoPO.getId()).equals(invite)) {
//                    SystemError.wrapBs("-1", "邀请码有误");
//                }
//                if (!baseGroupInfoPO.getStatus() || baseGroupInfoPO.getIsFreeze()) {
//                    SystemError.wrapBs("-1", "该邀请码已失效！");
//                }
//            }
                try {
                    inviteUid = McodeHandler.from32Radix(inviteCode.toUpperCase());
                } catch (Exception e) {
                    SystemError.wrapBs("-1", "邀请码有误");
                }
                LoginInfo inviteUserInfo = loginService.infoByUid(inviteUid+"");
                if (StringHandler.isEmpty(inviteUserInfo)) {
                    SystemError.wrapBs("-1", "邀请码有误");
                } else {
                    if (inviteUserInfo.getAccountStatus()!=0 ) {
                        SystemError.wrapBs("-1", "该邀请码已失效！");
                    }
                }
            }

            //用户不存在则注册
            wxLoginInfo.setAvatarUrl(StringHandler.isNotEmpty(wxLoginInfo.getAvatarUrl()) ? wxLoginInfo.getAvatarUrl() : DEFAULT_IMG);
            if (StringHandler.isNotEmpty(wxLoginInfo.getPhone())) {
                wxLoginInfo.setNickName(StringHandler.isNotEmpty(wxLoginInfo.getNickName()) ? wxLoginInfo.getNickName() : wxLoginInfo.getPhone().substring(wxLoginInfo.getPhone().length() - 5));
            }
            if (StringHandler.isEmpty(wxLoginInfo.getNickName())) {
                wxLoginInfo.setNickName(UUID.randomUUID().toString().substring(0, 7));
            }
            wxLoginInfo.ip = ip;
            if(type==3) {
                wxLoginInfo.inviteUid = inviteUid;
            }
            loginService.add(wxLoginInfo);
            if (StringHandler.isNotEmpty(wxLoginInfo.getUnionId())) {
                loginInfo = loginService.info(wxLoginInfo.getUnionId());
            } else if (StringHandler.isNotEmpty(wxLoginInfo.getPhone())) {
                loginInfo = loginService.infoByPhone(wxLoginInfo.getPhone());
            } else if (StringHandler.isNotEmpty(wxLoginInfo.getAppleId())) {
                loginInfo = loginService.infoByApple(wxLoginInfo.getAppleId());
            }
            //注册用户邀请码保存
//            if (isInvited && !"0" .equals(inviteCode)) {
//                groupInfoMapper.insertInviteInfo(StringHandler.getLong(loginInfo.getId()), invite, McodeHandler.from32Radix(invite));
//            }
            return loginService.loginUser(loginInfo);
        }
    }

    /**
     * 手机号登录的用户进行微信关联
     *
     * @param code
     * @return
     */
    @RequestMapping("relation/wx")
    public String relationWx(@RequestAttribute String uid, String code) {
        if (StringHandler.isEmpty(code)) {
            SystemError.wrapBs("500", "微信绑定失败");
        }
        //app判断
        AppInfo appInfo = AppInfoManager.get(Config.pp.get("appId"));
        if (null == appInfo) {
            return ResponseHandler.error("8002", "参数异常");
        }
        try {
            String strUri = String.format("https://api.weixin.qq.com/sns/oauth2/access_token?appid=%s&secret=%s&code=%s&grant_type=authorization_code", appInfo.getAppId(), appInfo.getSecret(), code);
            // 使用 Hutool开发工具包，执行请求接口，获取相关信息
            HttpResponse response = HttpRequest.get(strUri).execute();
            WxOAuth2AccessToken token = WxOAuth2AccessToken.fromJson(response.body());
            // 判断JSON对象中 unionid 是否存在
            if (StringHandler.isEmpty(token.getUnionId())) {
                // 不存在返回结果，code无效
                SystemError.wrapBs("500", "登录失败");
            }
            strUri = String.format("https://api.weixin.qq.com/sns/userinfo?access_token=%s&openid=%s&lang=%s", token.getAccessToken(), token.getOpenId(), "zh_CN");
            response = HttpRequest.get(strUri).execute();
            WxOAuth2UserInfo wxOAuth2UserInfo = WxOAuth2UserInfo.fromJson(response.body());

            //个人中心绑定微信需要判断该微信已注册
            LoginInfo loginInfoWx = loginService.info(wxOAuth2UserInfo.getUnionId());
            if (StringHandler.isNotEmpty(loginInfoWx)) {
                return ResponseHandler.error("500", "该微信已绑定");
            }

            LoginInfo loginInfo = WxOAuth2UserInfoTransformer.INSTANCE.apply(wxOAuth2UserInfo);
            loginInfo.setId(uid);
            loginInfo.setAppId(appInfo.getAppId());
            loginService.updateInfoByWx(loginInfo);

            return ResponseHandler.success();
        } catch (Exception e) {
            Logger.error("关联微信异常", e);
            return ResponseHandler.error("500", "微信绑定失败");
        }
    }

    /**
     * 第三方登录的需要关联手机号
     *
     * @param phone
     * @return
     */
    @RequestMapping("relation/phone")
    @Transactional
    public String relationPhone(@RequestAttribute String uid,@RequestAttribute String ip, String phone, String code, String inviteCode,String passWord,String passWordCk) {
        if(StringHandler.isEmpty(passWord)){
            SystemError.wrapBs("500", "密码不能为空");
        }
        if(StringHandler.isEmpty(passWordCk)){
            SystemError.wrapBs("500", "确认密码不能为空");
        }
        if(!passWord.equals(passWordCk)){
            SystemError.wrapBs("500", "两次密码输入不一致");
        }
        String sms = Redis.str.get(UserKey.codeByPhone(phone));
        if (StringHandler.isEmpty(sms)) {
            SystemError.wrapBs("500", "请先获取验证码");
        }
        if (!sms.equals(code)) {
            SystemError.wrapBs("500", "验证码已过期");
        }
        String invite = inviteCode;
        long inviteUid =0L;
        boolean isInvited = Boolean.parseBoolean(Config.pp.getOrDefault(BaseConstants.SwitchConstants.SWITCH_INVITE_CODE, "false"));
        if (isInvited && !"0" .equals(inviteCode)) {
            if (StringHandler.isEmpty(inviteCode)) {
                SystemError.wrapBs("-1", "邀请码必填");
            }

//            long groupId = 0;
//            try {
//                groupId = McodeHandler.from32Radix(inviteCode.toUpperCase());
//            } catch (Exception e) {
//                SystemError.wrapBs("-1", "邀请码有误");
//            }
//            BaseGroupInfoPO baseGroupInfoPO = groupInfoMapper.selectByPrimaryKey(groupId);
//            if (StringHandler.isEmpty(baseGroupInfoPO)) {
//                SystemError.wrapBs("-1", "邀请码有误");
//            } else {
//                if (!McodeHandler.to32Radix(baseGroupInfoPO.getId()).equals(invite)) {
//                    SystemError.wrapBs("-1", "邀请码有误");
//                }
//                if (!baseGroupInfoPO.getStatus() || baseGroupInfoPO.getIsFreeze()) {
//                    SystemError.wrapBs("-1", "该邀请码已失效！");
//                }
//            }
            try {
                inviteUid = McodeHandler.from32Radix(inviteCode.toUpperCase());
            } catch (Exception e) {
                SystemError.wrapBs("-1", "邀请码有误");
            }
            LoginInfo inviteUserInfo = loginService.infoByUid(inviteUid+"");
            if (StringHandler.isEmpty(inviteUserInfo)) {
                SystemError.wrapBs("-1", "邀请码有误");
            } else {
                if (inviteUserInfo.getAccountStatus()!=0 ) {
                    SystemError.wrapBs("-1", "该邀请码已失效！");
                }
            }
        }
        LoginInfo loginInfo = loginService.infoByPhone(phone);
        LoginInfo loginInfo2 = loginService.infoByUid(uid);
        if (StringHandler.isEmpty(loginInfo)) {
            loginInfo2.setPhone(phone);
            loginInfo2.setSalt(UUID.randomUUID().toString().substring(0, 4));
            loginInfo2.setPassword(MD5.md5(passWord + loginInfo2.getSalt()));
            loginInfo2.setInviteUid(inviteUid);
            loginService.updateInfoByPhone(loginInfo2);
            loginInfo = loginInfo2;
        } else {
            loginService.del(loginInfo2);
            if (StringHandler.isNotEmpty(loginInfo2.getAppleId())) {
                loginInfo.setAppleId(loginInfo2.getAppleId());
                loginService.updateInfoByApple(loginInfo);
            } else if (StringHandler.isNotEmpty(loginInfo2.getOpenId())) {
                loginInfo.setUnionId(loginInfo2.getUnionId());
                loginInfo.setAppId(loginInfo2.getAppId());
                loginInfo.setOpenId(loginInfo2.getOpenId());
                loginInfo.setNickName(loginInfo2.getNickName());
                loginInfo.setAvatarUrl(loginInfo2.getAvatarUrl());
                loginInfo.setGender(loginInfo2.getGender());
                loginInfo.setProvince(loginInfo2.getProvince());
                loginInfo.setCity(loginInfo2.getCity());
                loginInfo.setCountry(loginInfo2.getCountry());
                if(StringHandler.isEmpty(loginInfo.payPass)){
                    loginInfo.setSalt(UUID.randomUUID().toString().substring(0, 4));
                }
                loginInfo.setPassword(MD5.md5(passWord + loginInfo.getSalt()));
                loginInfo.setInviteUid(inviteUid);
                loginService.updateInfoByWx(loginInfo);
            }
        }
        Map<String, Object> login = login(loginInfo, inviteCode,1,ip);
        return ResponseHandler.success(login);
    }

    /**
     * 手机号登录的用户进行微信关联
     *
     * @param code
     * @return
     */
    @RequestMapping("relation/apple")
    public String relationApple(@RequestAttribute String uid, String code) {
        try {
            try {
                //验证identityToken
                if (!AppleUtils.verify(code)) {
                    return ResponseHandler.error("500", "登录失败");
                }
            } catch (Exception e) {
                Boolean verify = false;
                for (int i = 0; i < 3; i++) {
                    try {
                        verify = AppleUtils.verify(code);
                        if (verify) {
                            break;
                        }
                    } catch (Exception exception) {
                        exception.printStackTrace();
                    }
                }
                if (!verify) {
                    return ResponseHandler.error("500", "登录失败");
                }
            }
            //对identityToken解码
            JSONObject json = AppleUtils.parserIdentityToken(code);
            //验证通过，入库，生成token登录
            LoginInfo loginInfo = new LoginInfo();
            loginInfo.setId(uid);
            loginInfo.setAppleId(json.getString("sub"));
            loginService.updateInfoByApple(loginInfo);
            return ResponseHandler.success();
        } catch (Exception e) {
            Logger.error("关联苹果账号异常", e);
            return ResponseHandler.error("500", "绑定失败");
        }
    }

    @RequestMapping("logout")
    public String logout(@RequestAttribute Long uid,String token) {
        if (StringHandler.isNotEmpty(uid)) {
            loginService.logout(uid,token);
        }
        return ResponseHandler.success();
    }


    @RequestMapping("cancel")
    @Transactional(rollbackFor = Exception.class)
    public String cancel(@RequestAttribute Long uid) {
//        loginService.cancel(uid);
        //查看用户是不是还存在群聊
        List<String> userGroupList = userGroupMapper.findUserGroupList(uid);
        if (!userGroupList.isEmpty()) {
            return ResponseHandler.error("500", "清先退出所有群聊后，再尝试注销");
        }

        LoginInfo loginInfo = loginService.infoByUid(StringHandler.getString(uid));

        if (loginInfo.getAccountStatus() == 2) {
            SystemError.wrapBs("500", "您的账号已禁用，操作失败");
        }

        //修改用户信息表中的信息
        loginService.updateLocalInfoById(uid);

        //物理删除用户银行卡信息
        loginService.delUserBankInfo(uid);

        //物理删除用户银行卡信息
        loginService.delUserBankHjzfInfo(uid);

        //清理用户缓存数据
        LoginInfo cacheUser = UserUtils.getCacheUser(uid);
        String phoneKey = UserKey.uidByPhone(cacheUser.getPhone());
        Redis.key.del(phoneKey);
        String key = UserKey.userInfoByUid(uid);
        Redis.key.del(key);
        String unionIdKey = UserKey.uidByUnion(cacheUser.getUnionId());
        Redis.key.del(unionIdKey);
        return ResponseHandler.success();
    }
}
